Developers of many application programs (“applications”) implement the applications so that they can be customized by third parties. To customize an application, a third party develops custom code (e.g., addins and document-level customizations) that uses functionality exposed by the application. The custom code may improve the usability of the applications or provide additional functionality (e.g., domain-specific functionality). Such applications are referred to as “host applications” because the custom code is hosted within the process of the application. Developers of applications typically want to encourage the development of custom code for their applications to increase the demand for their applications. As a result, such developers may provide “runtimes” that facilitate the development of custom code. A runtime is code that is loaded along with custom code and provides services to the custom code. These services may include higher-level functionality than exposed by the application or may include domain-specific functionality. When an application is to load and start the execution of custom code, the application may load the runtime and direct the runtime to load and start the execution of the custom code.
Because of the ease of developing custom code as “managed code,” many applications support the execution of custom code in the .NET Framework provided by Microsoft Corporation. The .NET Framework provides a common language runtime (“CLR”) that provides high-level operating system type services to the managed programs (including custom code and applications) and serves as an execution engine for managed programs. The CLR ensures that managed programs do not take any unauthorized action. As such, the CLR acts as a “sandbox” within which managed programs execute. The CLR provides application domains (“appdomains”) in which different managed programs can execute to help ensure that an errant managed program will not unduly affect the execution of another managed program.
When an application starts, it may identify the custom code that is to be loaded and executed. The application may access registry entries that identify the custom code. When the application identifies custom code, it typically uses a loader object to load and start the execution of the custom code. The application may instantiate the loader object and may then invoke a load method of the loader object to effect the loading of the identified custom code. The loader object loads the runtime for the application and then directs the runtime to load the custom code. The application instantiates a loader object of a loader object class that is defined at compile time. Because the class is specified at compile time, the specific runtime or version of the runtime is effectively hard-coded into the application. This hard-coding of the version of the runtime presents several problems. An application and its runtime may be developed by different groups of developers, may be packaged as different products, and may have different release cycles for their versions. Because of the hard-coding, an application is typically programmed to load the version of the runtime that was current at the time of the application's release. Organizations, however, may be reluctant to upgrade to the new version of the application until the custom code that it relies upon is tested with the version of the runtime loaded by the application. This reluctance may slow the sales of the new version of the application. Another difficulty arises because a new version of the runtime may be released in between releases of the application. In such a case, the application cannot load custom code that relies on the new runtime until a new version of the application with its loader object updated is released or until the application is patched to access the new version of the runtime. Such patching, however, is both expensive and prone to errors.